package gamehistory.challenge;

import scg.gen.AccountAcceptTrans;
import scg.gen.AccountSolveTrans;
import scg.gen.ChallengeKind;
import scg.gen.OfferTrans;
import scg.gen.ProblemType;
import scg.gen.ProvideTrans;
import scg.gen.ReofferTrans;
import scg.gen.SolveTrans;
import utils.FormatUtilities;
import gamehistory.utils.xml.XMLModel;

/**
 * 
 * @author Brent Kersanske
 *
 */
public class ChallengeModel extends XMLModel {
	
	private static final String CHALLENGE 	   = "challenge";
	private static final String CHALLENGE_ID   = "id";
	private static final String KIND		   = "kind";
	private static final String PREDICATE	   = "predicate";
	private static final String CREATOR		   = "creator";
	private static final String ORIGINAL_PRICE = "originalPrice";
	private static final String ACCEPTED_PRICE = "acceptedPrice";
	private static final String ACCEPTOR	   = "acceptor";
	private static final String RESULT		   = "result";
	
	/* Floating challenges are challenges that are not accepted during the competition. */
	private static final String FLOATING	   = "floating";
	
	private int challengeID;
	private String creator;
	private String acceptor;
	private String result;
	private ChallengeKind kind;
	private ProblemType predicate;
	private double originalPrice;
	private double acceptedPrice;
	private OfferHistoryModel offerHistory;
	private SolveModel solveModel;
	
	private boolean solved;
	private boolean accepted;
		
	/**
	 * 
	 * @param creator
	 * @param originalOffer
	 */
	public ChallengeModel(String creator, OfferTrans originalOffer) {
		super(CHALLENGE);
		this.challengeID   = originalOffer.getChallengeid();
		this.kind		   = originalOffer.getKind();
		this.predicate	   = originalOffer.getPred();
		this.creator 	   = creator;
		/* Initially the challenge is floating. This will be changes when an accept transaction is assimilated. */
		this.result		   = FLOATING;
		this.accepted	   = false;
		this.solved		   = false;
		this.offerHistory  = new OfferHistoryModel(this.creator, originalOffer);
		this.originalPrice = originalOffer.getPrice();
	}
	
	/**
	 * 
	 * @return
	 */
	public Boolean isAccepted() {
		return this.accepted;
	}
	
	/**
	 * 
	 * @param playerName
	 * @param reofferTransaction
	 */
	public void assimilateReofferTransaction(String playerName, ReofferTrans reofferTransaction) {
		this.offerHistory.assimilateReoffer(playerName, reofferTransaction);
	}
	
	/**
	 * 
	 * @param playerName
	 * @param provideTransaction
	 */
	public void assimilateProvideTransaction(String playerName, ProvideTrans provideTransaction) {
		// TODO: Do something with provides.
	}

	/**
	 * 
	 * @param playerName
	 * @param solveTransaction
	 */
	public void assimilateSolveTransaction(String playerName, SolveTrans solveTransaction) {
		this.solveModel = new SolveModel(playerName, solveTransaction);
	}
	
	/**
	 * 
	 * @param playerName
	 * @param accountAcceptTransaction
	 */
	public void assimilateAccountAcceptTransaction(String playerName, AccountAcceptTrans accountAcceptTransaction) {
		this.acceptor 	   = playerName;
		this.acceptedPrice = accountAcceptTransaction.getAmount();
		this.accepted	   = true;
	}

	/**
	 * 
	 * @param accountSolveTransaction
	 */
	public void assimilateAccountSolveTransaction(AccountSolveTrans accountSolveTransaction) {
		this.solveModel.assimilateAccountSolveTransaction(this.acceptedPrice, accountSolveTransaction);
		this.result = this.solveModel.getResult();
		this.solved = true;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void buildModel() {
		addAttribute(CHALLENGE_ID,   String.valueOf(this.challengeID));
		addAttribute(CREATOR, 	     this.creator);
		addAttribute(KIND,		     this.kind.toString());
		addAttribute(PREDICATE,	     this.predicate.toString());
		addAttribute(ORIGINAL_PRICE, FormatUtilities.formatDouble(this.originalPrice));
		this.offerHistory.buildModel();
		addChildModel(this.offerHistory);
		if(accepted) {
			addAttribute(ACCEPTOR, 	     this.acceptor);
			addAttribute(ACCEPTED_PRICE, FormatUtilities.formatDouble(this.acceptedPrice));
		}
		if(solved) {
			this.solveModel.buildModel();
			addChildModel(this.solveModel);
		}
		addAttribute(RESULT, this.result);
	}
}
